/*
 * REFThreadPool.h
 *
 *  Created on: Apr 22, 2013
 *      Author: Lucifer
 */

#ifndef REFTHREADPOOL_H_
#define REFTHREADPOOL_H_

namespace BFX
{

//////////////////////////////////////////////////////////////////////////////

/**
 * Provides a pool of threads that can be used to execute tasks, post work items, process asynchronous I/O.
 */
class REFThreadPool : public REFObject
{
public:
	/**
	 * Creates a new instance with the given initial parameters.
	 * @param[in] nCoreThreads The number of threads to keep in the pool, even if they are idle.
	 * @param[in] nMaxThreads The maximum number of threads to allow in the pool.
	 * @param[in] nIdleTimeoutInSecounds The expiration value, in seconds. When the number of threads is greater than the core, this
	 *		is the maximum time that excess idle threads will wait for new tasks before terminating.
	 */
	REFThreadPool(int nCoreThreads, int nMaxThreads, int nIdleTimeoutInSecounds);

	/**
	 * Destroys the instance of thread pool.
	 * Before the pool destroyed, It will force to stop all worker threads even they are still alive.
	 */
	virtual ~REFThreadPool();

	/**
	 * Starts thread pool.
	 */
	virtual void Start();

	/**
	 * Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted.
	 */
	virtual void Shutdown();

	/**
	 * Queues a method for execution. The method executes when a thread pool thread becomes available.
	 * @param[in] pCallback The pointer of BFX::REFCallback to be executed.
	 * @param[in] pContext An pointer containing data to be used by the method.
	 * @return True if successful; false if the threadpool has not been started or already shutdown.
	 */
	virtual bool QueueRequest(REFThreadCallback* pCallback);

	/**
	 * Queues a method for execution. The method executes when a thread pool thread becomes available.
	 * @param[in] fnCallback The functor object of method to be executed.
	 * @return True if successful; false if the threadpool has not been started or already shutdown.
	 */
	virtual bool QueueRequest(ThreadCallback pfnCallback);

protected:
	// Returns the value indicates whether the pool is initialized.
	bool IsInitialized()
	{
		return (m_lInitialized == -1);
	}
	// Returns the value indicates whether the pool requires more workers.
	bool NewWorkerRequired() const;
	// Creates a new worker thread.
	void CreateWorkerThread();

	// Enqueue a work request.
	void EnqueueWorkRequest(REFThreadCallback* pWorkRequest);
	// Dequeue a work request.
	REFThreadCallback* DequeueWorkRequest();
	// Execute a work request.
	void ExecuteWorkRequest(REFThreadCallback* pWorkRequest);

	// Thread entry.
	static void __cdecl WorkerThreadProc(REFThreadPool* pThreadPool);
	void ThreadProc();

private:
	// Initial parameters
	int		m_nMinLimitTotalWorkerThreads;
	int		m_nMaxLimitTotalWorkerThreads;
	int		m_nIdleWokerTimeout;

	long	m_lInitialized;						// indicator of whether the threadpool is initialized.
	bool	m_bShuttingDown;

	int		m_nNumWorkerThreads;				// total number of worker threads created
	int		m_nNumIdleWorkerThreads;			// how many threads waiting for work

	Mutex	m_workerCriticalSection;
	REF<REFThreadEvent>		m_pWorkRequestNotification;
	List<REF<REFThreadCallback> > m_workRequests;		// work request queue.
};

} /* namespace BFX */

#endif /* REFTHREADPOOL_H_ */
